﻿using System.Collections.Generic;
using System.IO;
using System.Text;
using WGS84;

namespace OSMLib
{
    public class OsmBinLoader
    {
        private readonly Dictionary<int, IOsmWay> _ways;
        private readonly List<IOsmNode> _nodes;

        public OsmBinLoader(Dictionary<int, IOsmWay> ways, List<IOsmNode> nodes)
        {
            _ways = ways;
            _nodes = nodes;
        }

        public void ReadFile(string filename)
        {
            if (!File.Exists(filename))
            {
                return;
            }

            _ways.Clear();
            _nodes.Clear();

            FileStream fs = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read);

            var unicode = new UnicodeEncoding();

            using (var br = new BinaryReader(fs, unicode))
            {
                ReadWays(br);
                ReadNodes(br);
                br.Close();
            }
        }

        private void ReadWays(BinaryReader br)
        {
            int wayCount = br.ReadInt32();

            for (int x = 0; x < wayCount; x++)
            {
                int wayId = br.ReadInt32();
                var way = new OsmWay(wayId);

                int nodeCount = br.ReadInt32();
                for (int nc = 0; nc < nodeCount; nc++)
                {
                    double lat = br.ReadDouble();
                    double lon = br.ReadDouble();
                    var node = new OsmNode(new Wgs84Coordinate(lat, lon));
                    int nodeTagCount = br.ReadInt32();

                    for (int ntc = 0; ntc < nodeTagCount; ntc++)
                    {
                        string key = br.ReadString();
                        string value = br.ReadString();
                        node._tags.Add(key, value);
                    }
                    way.AddNode(node);
                }

                int tagCount = br.ReadInt32();
                for (int tc = 0; tc < tagCount; tc++)
                {
                    string key = br.ReadString();
                    int count = br.ReadInt32();
                    var tagValues = new List<string>();

                    for (int wayTag = 0; wayTag < count; wayTag++)
                    {
                        string value = br.ReadString();
                        tagValues.Add(value);
                    }

                    way._tags.Add(key, tagValues);
                }
                way.BuildBoundingBox();
                _ways.Add(wayId, way);
            }
        }

        private void ReadNodes(BinaryReader br)
        {
            int nodeCount = br.ReadInt32();
            for (int nc = 0; nc < nodeCount; nc++)
            {
                double lat = br.ReadDouble();
                double lon = br.ReadDouble();
                var node = new OsmNode(new Wgs84Coordinate(lat, lon));
                int nodeTagCount = br.ReadInt32();

                for (int ntc = 0; ntc < nodeTagCount; ntc++)
                {
                    string key = br.ReadString();
                    string value = br.ReadString();
                    node._tags.Add(key, value);
                }
                _nodes.Add(node);
            }
        }
    }
}
